#ifndef __MY_SERVER__
#define __MY_SERVER__
#include <time.h>
#include "Data.hpp"
#include "httplib.h" //默认线程池大小为8个
#include <iconv.h>
extern Cloud::DataManger *datamanger;
namespace Cloud
{
    class Server // 服务器业务处理类
    {
    private:
        int server_port;
        string server_ip;
        string download_prefix;
        httplib::Server _server;

    public:
        Server()
        {
            server_ip = Cloud::Config::GetInstance()->GetServerIp();
            server_port = Cloud::Config::GetInstance()->GetServerPort();
            download_prefix = Cloud::Config::GetInstance()->GetDownLoadprefix();
        }
        static string TimeToString(time_t &t)
        {
            std::string tmp = std::ctime(&t);
            return tmp;
        }
        static string GetETags(const Cloud::BackupInfo &Info) // 设置ETags用来表示一个文件是否修改，若没修改，则当下次下载链接到来
                                                              // 客户端直接在缓存中取
        {
            stringstream etag;
            etag << FileUtil(Info.realpath).GetFileName() << "-" << to_string(Info.fsize) << "-" << to_string(Info.mtime);
            // string etag = FileUtil(Info.realpath).GetFileName();
            // etag += "-";
            // etag += to_string(Info.fsize);
            // etag += "-";
            // etag += to_string(Info.mtime);
            return etag.str();
        }
  
        void RunModule()
        {

            _server.Post("/upload", [](const httplib::Request &req, httplib::Response &res)
                         {
                             auto ret = req.has_file("file");
                             if (ret == false)
                             {
                                res.status=400;
                                WARN("%s","upload File is fail");
                                 return;
                             }
                 
                             struct httplib::MultipartFormData item;
                             item = req.get_file_value("file");
                         
                             string back_dir = Cloud::Config::GetInstance()->GetBackDir();
                             string realpath = back_dir+Cloud::FileUtil(item.filename).GetFileName();

                             DEBUG("%s%s", "upload a File success!,FilePath:", realpath.c_str());
                             
                             Cloud::FileUtil fu(realpath);
                             fu.SetCentent(item.content);//先存在磁盘中

                             Cloud::BackupInfo Info(realpath);
                             datamanger->Insert(Info);

                             try {
                            // 判断文件大小是否小于64MB（64 * 1024 * 1024 bytes）
                             if (item.content.size() <= 64 * 1024 * 1024) {
                                // 创建Redis连接
                                auto redis = sw::redis::Redis("tcp://redis:6379/1");
                                string ret = redis.ping();
                                if(ret=="PONG")
                                    INFO("Redis Init Complate,Establish a link");
                                
                                // 将文件内容存储到Redis并设置过期时间为1小时（3600秒）
                                redis.set(realpath, sw::redis::StringView(item.content.data(), item.content.size()),std::chrono::seconds(3600));
                                INFO("Redis Inserted a piece of Data,%s,Expiration date is 3600s",realpath.c_str());
                             }
                            } catch (const std::exception &e) {
                                WARN("Redis operation failed: %s", e.what());
                                res.status = 500;
                                return;
                            }
                             res.status = 200; });

            string download_url = download_prefix + "(.*)";
            _server.Get(download_url, [](const httplib::Request &req, httplib::Response &res)
                        {                          
                            Cloud::BackupInfo Info;
                            datamanger->GetOneByUrl(req.path, &Info);
                            Cloud::FileUtil fu(Info.realpath);
                            bool fromRedis = false;

                            try {
                                // 创建Redis连接
                                auto redis = sw::redis::Redis("tcp://redis:6379/1");
            
                   
                                // 尝试从Redis获取数据
                                auto ret = redis.exists(Info.realpath);

                                if (ret) {
                                    // 如果Redis中存在数据
                                    fromRedis = true;
                                    // 从Redis获取文件内容
                                    auto fileData = redis.get(Info.realpath);
                                    if (fileData) {
                                        fu.SetCentent(*fileData);
                                    }
                                }
                            } catch (const std::exception &e) {
                                WARN("Redis operation failed: %s", e.what());
                            }

                             // 如果Redis中没有找到数据，从MySQL获取
                            if (!fromRedis) {
                                // 判断下载文件是否压缩，压缩先解压，然后删除压缩包
                                if (Info.pack_flag == true)
                                {
                                    fu.UnCompress();
                                    Info.pack_flag = false;
                                    Info.packRunning=false;
                                    datamanger->Update(Info);
                                }
                            }

                            bool retrans = false; // 断点续传标志位
                            //FileUtil fu(Info.realpath);
                            string old_etags;
                            // 判读正常下载还是断点续传
                            if (req.has_header("If-Range"))//文件唯一标识符
                            {
                                old_etags = req.get_header_value("If-Range");
                                if (old_etags == GetETags(Info)) // 如果请求中的If-Range和服务器的etag不一致，则正常下载
                                {
                                    retrans = true;
                                }
                            }               
                            if (retrans) // 断点续传
                            {
                                DEBUG("%s", "GET a Client RangeDownload request!");
                                //根据Range字段，get_header_value("Range")获取到字段值，通过解析，取出begin和end，对body进行截断
                                fu.GetCentent(&res.body);
                                res.set_header("ETag", GetETags(Info));
                                res.set_header("Accept-Ranges", "bytes"); // 标识自身支持范围请求,当浏览器发现Accept-Ranges 头时，可以尝试继续中断了的下载
                                res.set_header("Content-Type", "application/octet-stream");
                                // 返回当前接受的范围和文件总大小
                                // res.set_hreader("Content-Range","bytes start-end/fsize") httplib自己进行填充了
                                res.status = 206;
                            }
                            else
                            {
                                DEBUG("%s", "GET a Client Download request!");
                                // 获取下载文件正文内容
                                fu.GetCentent(&res.body);
                                //  设置响应头部字段
                                //  设置ETags: "filename-size-mtime⼀个能够唯⼀标识⽂件的数据"
                                res.set_header("ETag", GetETags(Info));                    // 用来表示客户端请求文件与服务器备份文件是否一致
                                res.set_header("Content-Type", "application/octet-stream"); // 定义网络文件的类型，以二进制流方式处理
                                res.set_header("Accept-Ranges", "bytes");                   // 告诉客户端服务器支持断点续传
                                res.status = 200;
                            } });
            _server.Get("/", [](const httplib::Request &req, httplib::Response &res)
                        {

    std::vector<Cloud::BackupInfo> array;
    datamanger->GetAll(&array);
    DEBUG("%s", "GET a Client listview request!");
    std::stringstream ss;
    ss << "<html><head><meta charset=\"UTF-8\"><title>Download</title>";
    ss << "<style>";
    ss << "body { font-family: Arial, sans-serif; background-color: #f4f4f9; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }";
    ss << ".upload-container { background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); text-align: center; }";
    ss << ".upload-container h2 { color: #333; margin-bottom: 20px; }";
    ss << ".upload-container form { display: flex; flex-direction: column; align-items: center; }";
    ss << ".upload-container input[type='file'] { margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; }";
    ss << ".upload-container input[type='submit'] { background-color: #007bff; color: #fff; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-size: 16px; }";
    ss << ".upload-container input[type='submit']:hover { background-color: #0056b3; }";
    ss << "</style>";
    ss << "</head>";

    ss << "<body>";
    ss << "<div class='upload-container'>";
    ss << "<h2>文件下载</h2>";
    ss << "<table border='1'>";
    ss << "<tr><th>文件名</th><th>上传时间</th><th>大小 (KB)</th></tr>";
    for (auto &e : array) {
        ss << "<tr>";
        std::string filename = FileUtil(e.realpath).GetFileName();
        ss << "<td><a href='" << e.url << "'>" << filename << "</a></td>";
        ss << "<td align='right'>" << TimeToString(e.atime) << "</td>";
        ss << "<td align='right'>" << e.fsize / 1024 << "k</td>";
        ss << "</tr>";
    }
    ss << "</table>";
    ss << "</div>";
    ss << "</body></html>";

    res.body = ss.str();
    res.set_header("Content-Type", "text/html");
    res.status = 200; });

            _server.Get("/listshow", [](const httplib::Request &req, httplib::Response &res)
                        {
    std::vector<Cloud::BackupInfo> array;
    datamanger->GetAll(&array);
    DEBUG("%s", "GET a Client listview request!");
    std::stringstream ss;
    ss << "<html><head><meta charset=\"UTF-8\"><title>Download</title>";
    ss << "<style>";
    ss << "body { font-family: Arial, sans-serif; background-color: #f4f4f9; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; }";
    ss << ".upload-container { background: #fff; padding: 20px; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); text-align: center; }";
    ss << ".upload-container h2 { color: #333; margin-bottom: 20px; }";
    ss << ".upload-container form { display: flex; flex-direction: column; align-items: center; }";
    ss << ".upload-container input[type='file'] { margin-bottom: 20px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; }";
    ss << ".upload-container input[type='submit'] { background-color: #007bff; color: #fff; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-size: 16px; }";
    ss << ".upload-container input[type='submit']:hover { background-color: #0056b3; }";
    ss << "</style>";
    ss << "</head>";

    ss << "<body>";
    ss << "<div class='upload-container'>";
    ss << "<h2>文件下载</h2>";
    ss << "<table border='1'>";
    ss << "<tr><th>文件名</th><th>上传时间</th><th>大小 (KB)</th></tr>";
    for (auto &e : array) {
        ss << "<tr>";
        std::string filename = FileUtil(e.realpath).GetFileName();
        ss << "<td><a href='" << e.url << "'>" << filename << "</a></td>";
        ss << "<td align='right'>" << TimeToString(e.atime) << "</td>";
        ss << "<td align='right'>" << e.fsize / 1024 << "k</td>";
        ss << "</tr>";
    }
    ss << "</table>";
    ss << "</div>";
    ss << "</body></html>";

    res.body = ss.str();
    res.set_header("Content-Type", "text/html");
    res.status = 200; });
            _server.listen(server_ip.c_str(), server_port);
        }
    };
}

#endif